using System.Collections.Generic;
using System.Text;
using NUnit.Framework;
using Rhino.Mocks;

namespace MvpFramework.UnitTests
{
    [TestFixture]
    public class A_Navigator
    {
        private IHttpResponse response;
        private Navigator navigator;
        private IMvpViewLocationRepository repository;

        [SetUp]
        public void Arrange()
        {
            response = MockRepository.GenerateMock<IHttpResponse>();
            repository = MockRepository.GenerateMock<IMvpViewLocationRepository>();
        }
        public void Act()
        {
            navigator = new Navigator(response,repository);
        }
        
        [Test]
        public void will_use_HttpResponse_when_NavigateTo_is_called()
        {
            const string navigateTo = "somewhere.aspx";
            Act();
            navigator.NavigateTo(navigateTo);

            response.AssertWasCalled(r => r.Redirect(navigateTo));
        }
        [Test]
        public void will_use_a_IMvpViewLocationRepository_to_find_the_views_location()
        {
            const string theLocation = "theLocation";
            repository.Stub(r => r.GetLocationFor<IMvpView>()).Return(theLocation);
            
            Act();
            navigator.NavigateTo<IMvpView>();

            response.AssertWasCalled(r => r.Redirect(theLocation));
        }
        [Test]
        public void will_append_options_to_NavigateTo_when_specified()
        {
            var options = new Dictionary<string, object>();
            var key = "key";
            var value = "value";
            options.Add(key, value);
            
            //Repo
            const string theLocation = "theLocation";
            repository.Stub(r => r.GetLocationFor<IMvpView>()).Return(theLocation);
            var expectedLocation = GetExpectedLocaction(options, theLocation);
            
            Act();
            navigator.NavigateTo<IMvpView>(options);
           
            response.AssertWasCalled(r => r.Redirect(expectedLocation));
        }

        private static string GetExpectedLocaction(Dictionary<string, object> options, string theLocation)
        {
            var expectedRedirect = new StringBuilder(theLocation);
            expectedRedirect.Append("?");
            foreach (var item  in options)
            {
                expectedRedirect.AppendFormat("{0}={1}&", item.Key, item.Value);
            }
            //Remove that trailing & character
            return expectedRedirect.ToString().TrimEnd('&');
        }
    }
}